home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / gcc / ixemlsrc.lha / ixemul / library / stat.c < prev    next >
C/C++ Source or Header  |  1996-03-13  |  7KB  |  236 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  stat.c,v 1.1.1.1 1994/04/04 04:30:35 amiga Exp
  20.  *
  21.  *  stat.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:35  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1993/11/05  22:03:10  mwild
  26.  *  grp/oth support, plus new feature
  27.  *
  28.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36. #include <stdio.h>
  37. #include <string.h>
  38.  
  39. #ifndef ST_ROOT
  40. #define ST_ROOT        1
  41. #define ST_USERDIR     2
  42. #define ST_SOFTLINK    3
  43. #define ST_LINKDIR    4
  44. #define ST_FILE        -3
  45. #define ST_LINKFILE    -4
  46. #endif
  47.  
  48. #ifndef ERROR_IS_SOFT_LINK
  49. #define ERROR_IS_SOFT_LINK  233
  50. #endif
  51.  
  52. /* currently, links are quite buggy.. hope this get cleaned up RSN ;-) */
  53.  
  54. static int
  55. __stat(const char *fname, struct stat *stb, BPTR (*lock_func)())
  56. {
  57.   BPTR lock;
  58.   long mode;
  59.   struct FileInfoBlock *fib;
  60.   struct InfoData *info;
  61.   int omask, err = 0;
  62.  
  63.   bzero (stb, sizeof(*stb));
  64.  
  65.   omask = syscall (SYS_sigsetmask, ~0);
  66.  
  67.   if (!(lock = (*lock_func) (fname, ACCESS_READ)))
  68.     {
  69.       err = IoErr ();
  70.  
  71.       /* take special care of NIL:, /dev/null and friends ;-) */
  72.       if (err == 4242)
  73.         {
  74.           stb->st_mode = S_IFCHR | 0777;
  75.           stb->st_nlink = 1;
  76.           stb->st_blksize = ix.ix_fs_buf_factor * 512;
  77.           stb->st_blocks = 0;
  78.           goto rest_sigmask;
  79.         }
  80.  
  81.       KPRINTF (("__stat: lock %s failed, err = %ld.\n", fname, err));
  82.       if (err == ERROR_IS_SOFT_LINK)
  83.     {
  84.       /* provide some default stb.. we can't get anymore info than
  85.        * that. Symlinks should work with Lock(), but till now they
  86.        * don't ;-( */
  87.       stb->st_handler = (int) DeviceProc ((UBYTE *)fname);
  88.       stb->st_dev = (dev_t) stb->st_handler;
  89.       /* HELP! no way to reach the fib of this entry except when
  90.        * scanning the parent directory, but this is NOT acceptable ! */
  91.       stb->st_ino = 123;
  92.       /* this is the most important entry ;-) */
  93.       stb->st_mode = S_IFLNK | 0777;
  94.       stb->st_size = 1024; /* again, this should be availabe... */
  95.       stb->st_nlink = 1;
  96.       stb->st_uid = stb->st_gid = stb->st_rdev = 0;
  97.       /* again, these values ARE accessible, but only by ExNext */
  98.       stb->st_atime = stb->st_mtime = stb->st_ctime = 0;
  99.       stb->st_blksize = stb->st_blocks = 0;
  100.       goto rest_sigmask;
  101.         }
  102. error:
  103.       syscall (SYS_sigsetmask, omask);
  104.       errno = __ioerr_to_errno (err);
  105.       KPRINTF (("ioerr = %ld, &errno = %lx, errno = %ld\n", err, &errno, errno));
  106.       return -1;
  107.     }
  108.   KPRINTF (("__stat: lock %s ok.\n",fname));
  109.  
  110.   /* alloca() returns stack memory, so it's guaranteed to be word 
  111.    * aligned (anything else would be deadly for the sp...) Since DOS needs
  112.    * long aligned data, we'll allocate 1 word more and adjust as needed */
  113.   fib = alloca (sizeof(*fib) + 2);
  114.   /* DON'T use LONG_ALIGN(alloca(..)), the argument is evaluated more than once! */
  115.   fib = LONG_ALIGN (fib);
  116.  
  117.   info = alloca (sizeof(*info) + 2);
  118.   info = LONG_ALIGN (info);
  119.  
  120.   if (!(Examine (lock, fib)))
  121.     {
  122.       __unlock (lock);
  123.       goto error;
  124.     }
  125.  
  126.   stb->st_nlink = 1; /* always one link entry per file, unless... */
  127.  
  128.   mode = 0L;
  129.   stb->st_amode = fib->fib_Protection;
  130.   if (!(fib->fib_Protection & FIBF_EXECUTE))
  131.     mode |= S_IXUSR;
  132.   else if (fib->fib_Protection & FIBF_SCRIPT)
  133.     mode |= S_IXUSR;
  134.   if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
  135.     mode |= S_IWUSR;
  136.   if (!(fib->fib_Protection & FIBF_READ))
  137.     mode |= S_IRUSR;
  138. #ifdef FIBF_GRP_EXECUTE
  139.   /* FIBF_GRP_EXECUTE requires at least OS3 headers */
  140.   if (fib->fib_Protection & FIBF_GRP_EXECUTE)
  141.     mode |= S_IXGRP;
  142.   if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
  143.     mode |= S_IWGRP;
  144.   if (fib->fib_Protection & FIBF_GRP_READ)
  145.     mode |= S_IRGRP;
  146.   if (fib->fib_Protection & FIBF_OTR_EXECUTE)
  147.     mode |= S_IXOTH;
  148.   if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
  149.     mode |= S_IWOTH;
  150.   if (fib->fib_Protection & FIBF_OTR_READ)
  151.     mode |= S_IROTH;
  152. #endif
  153.  
  154.   switch (fib->fib_DirEntryType)
  155.     {
  156.     case ST_LINKDIR:
  157.       stb->st_nlink ++;  /* we never get more than a link count of two.. */
  158.     case ST_ROOT:
  159.     case ST_USERDIR:
  160.       mode |= S_IFDIR;
  161.       break;
  162.  
  163.     /* at the moment, we NEVER get this entry, since we can't get a lock
  164.      * on a symlink */
  165.     case ST_SOFTLINK:
  166.       mode |= S_IFLNK;
  167.       break;
  168.  
  169.     case ST_LINKFILE:
  170.       stb->st_nlink ++;
  171.     case ST_FILE:
  172.     default:
  173.       mode |= S_IFREG;
  174.     }
  175.  
  176.   stb->st_mode = mode;
  177.   
  178.   /* support for annotated attributes (cool name ;-)) */
  179.   if (! strncmp (fib->fib_Comment, "!SP!", 4))
  180.     {
  181.       int sp_mode, sp_addr;
  182.  
  183.       if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
  184.         stb->st_mode = sp_mode;
  185.     }
  186.   
  187.   /* some kind of a default-size for directories... */
  188.   stb->st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024; 
  189.   stb->st_handler = (long)((struct FileLock *)((long)lock << 2))->fl_Task;
  190.   stb->st_dev = (dev_t)stb->st_handler; /* trunc to 16 bit */
  191.   stb->st_ino = fib->fib_DiskKey; 
  192.   stb->st_atime =
  193.   stb->st_ctime =
  194.   stb->st_mtime = (8*365+2)*24*3600 + ix_get_gmt_offset() +
  195.           fib->fib_Date.ds_Days * 24 * 60 * 60 +
  196.           fib->fib_Date.ds_Minute * 60 +
  197.           fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  198.   /* in a try to count the blocks used for filemanagement, we add one for
  199.    * the fileheader. Note, that this is wrong for large files, where there
  200.    * are some extension-blocks as well */
  201.   stb->st_blocks = fib->fib_NumBlocks + 1;
  202.   
  203.   bzero (info, sizeof (*info));
  204.   stb->st_blksize = 0;
  205.   if (Info(lock, info))
  206.     /* optimal for fileio is as high as possible ;-) This is a
  207.      * compromise between "as high as possible" and not too restricitve
  208.      * for people low on memory */
  209.     stb->st_blksize = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
  210.  
  211.   if (! stb->st_blksize) stb->st_blksize = 512;
  212.  
  213.   __unlock (lock);
  214.  
  215. rest_sigmask:
  216.   syscall (SYS_sigsetmask, omask);
  217.   errno = 0;
  218.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  219.   return 0;
  220. }
  221.  
  222. /***************************************************************************/
  223.  
  224. int
  225. stat (const char *fname, struct stat *stb)
  226. {
  227.   return __stat (fname, stb, __lock);
  228. }
  229.  
  230. int
  231. lstat (const char *fname, struct stat *stb)
  232. {
  233.   return __stat (fname, stb, __llock);
  234. }
  235.  
  236.